<?php
class Budget extends AppModel {
    var $validate = array(
        'budget_year' => array(
            'required' => array(
                'rule' => 'alphanumeric',
                'message' => 'Wajib diisi dengan tahun'
            ),
            'maxlength' => array(
                'rule' => array('maxlength', 4),
                'message' => 'Wajib diisi dengan tahun'
            ),
            'minlength' => array(
                'rule' => array('minlength', 4),
                'message' => 'Wajib diisi dengan tahun'
            ),
            'unique' => array(
                'rule' => array('vUniqueBudget'),
                'message' => 'Anggaran seperti ini pada tahun yang sama sudah ada'
            )
        ),
        'unit_code_id' => array(
            'valid' => array(
                'rule' => 'vUnit',
                'message' => 'Wajib diisi dengan Unit Kerja'
            )
        ),
        'activity_id' => array(
            'valid' => array(
                'rule' => 'vActivity',
                'message' => 'Wajib diisi dengan Sub Kegiatan yang tidak ada sub di bawahnya'
            )
        )
    );

    var $hasMany = array(
        'BudgetDetail' => array(
            'dependent' => true
        )
    );

    var $belongsTo = array(
        'UnitCode', 'Activity',
        'User' => array(
            'foreignKey' => 'created_by'
        )
    );

    function getTree($year = null) {
        if (is_null($year)) {
            $year = date('Y');
        }
        $actvTree = $this->Activity->getTree();

        // get list of activity child
        $_ac = $this->BudgetDetail->ActivityChild->find('all', array(
            'fields' => array('id', 'code', 'name'),
            'recursive' => -1,
            'order' => 'id ASC'
        ));
        $ac = array();
        foreach ( $_ac as $__ac ) {
            $ac[$__ac['ActivityChild']['id']] = array(
                'code' => $__ac['ActivityChild']['code'],
                'name' => $__ac['ActivityChild']['name']
            );
        }

        // get list of volumes
        $vol = $this->BudgetDetail->BudgetDetailDescription->Volume->find('list', array(
            'recursive' => -1,
            'order' => 'id ASC'
        ));

        $this->Behaviors->attach('Containable');
        $fields = array('id', 'activity_id', 'budget_year');
        $contain = array(
            'BudgetDetail' => array(
                'fields' => array('activity_child_id'),
                'order' => 'BudgetDetail.id ASC',
                'BudgetDetailDescription' => array(
                    'fields' => array(
                        'unit_count', 'unit_amount', 'description',
                        'volume_id', 'fund_source'
                    ),
                    'order' => 'BudgetDetailDescription.budget_detail_id ASC, ' .
                        'BudgetDetailDescription.id ASC'
                )
            )
        );
        $conditions = array(
            'Budget.budget_year' => $year
        );
        $order = 'Budget.id ASC';
        $records = $this->find('all', compact(
            'conditions', 'fields', 'order', 'limit',
            'page', 'recursive', 'contain'
            )
        );

        // get transaction
        ClassRegistry::init('Transaction');
        $Transaction = new Transaction;
        $T = $Transaction->getRealizationMAK($year);


        // hold total realizations that match with budget
        // definition
        $realizations = 0;

        // hold total realizations that didn't match with budget
        // definition
        $unmatchRealizations = 0;

        foreach ( $records as $key => $record ) {
            $totalMaster = 0;
            $c1 = 0;
            $c1__ = 0;

            $actvTree[$record['Budget']['activity_id']]['children'] = array();

            foreach ( $record['BudgetDetail'] as $_k => $budget_detail ) {
                $c1__ = $c1++;
                $actvTree[$record['Budget']['activity_id']]['children'][$c1__] = array(
                    'code' => $ac[$budget_detail['activity_child_id']]['code'],
                    'name' => $ac[$budget_detail['activity_child_id']]['name'],
                    'volume' => '',
                    'unit_amount' => '',
                    'total' => '',
                    'fund_source' => ''
                );

                // fill realization here, avoiding undefined index on $T
                if ( $ac[$budget_detail['activity_child_id']]['code'] &&
                     isset($T[$record['Budget']['activity_id']]
                        [$ac[$budget_detail['activity_child_id']]['code']]) ) {


                    $actvTree[$record['Budget']['activity_id']]['children'][$c1__]
                        ['realization'] = $T[$record['Budget']['activity_id']]
                            [$ac[$budget_detail['activity_child_id']]['code']]['total'];
                    $realizations += $T[$record['Budget']['activity_id']]
                            [$ac[$budget_detail['activity_child_id']]['code']]['total'];

                    // unset realization for particular mak
                    // so we can calculate unmatchRealizations
                    unset($T[$record['Budget']['activity_id']]
                            [$ac[$budget_detail['activity_child_id']]['code']]);
                }
                $total = 0;
                $__tot = 0;

                // get description of each childs
                foreach ( $budget_detail['BudgetDetailDescription'] as
                    $__k => $budget_description ) {

                    $__tot  = ($budget_description['unit_count']*$budget_description['unit_amount']);
                    $total += $__tot;
                    $totalMaster += $__tot;
                    $fundSource = $this->__niceFundSourceName(
                        $budget_description['fund_source']
                    );

                    $actvTree[$record['Budget']['activity_id']]['children'][$c1++] = array(
                        'code' => '',
                        'name' => '- ' . $budget_description['description'],
                        'volume' => number_format(
                            $budget_description['unit_count'],2,',','') . ' ' .
                            $vol[$budget_description['volume_id']],
                        'unit_amount' => number_format(
                            $budget_description['unit_amount'],2,'.',','),
                        'total' => number_format($__tot,2,'.',','),
                        'fund_source' => $fundSource
                    );
                }

                // now set the total
                $actvTree[$record['Budget']['activity_id']]
                    ['children'][$c1__]['total'] =
                        number_format($total,2,'.',',');

                // fill percentage of realization/total and remaining,
                // avoiding undefined index on $T
                if ( isset($actvTree[$record['Budget']['activity_id']]
                    ['children'][$c1__]['realization']) ) {

                    $actvTree[$record['Budget']['activity_id']]
                    ['children'][$c1__]['remain'] = $total -
                        $actvTree[$record['Budget']['activity_id']]
                            ['children'][$c1__]['realization'];

                    $actvTree[$record['Budget']['activity_id']]
                    ['children'][$c1__]['percent'] =
                        ($actvTree[$record['Budget']['activity_id']]
                            ['children'][$c1__]['realization']/$total)*100;
                }
            }
            $actvTree[$record['Budget']['activity_id']]['total'] = $totalMaster;
        }

        foreach ($actvTree as $actId => $act) {
            if ( isset($act['parent_id']) && $act['parent_id'] ) {
                if ( !isset($act['total']) ) {

                } else {
                    if ( !isset($actvTree[$act['parent_id']]['total']) ) {
                        $actvTree[$act['parent_id']]['total'] = $act['total'];
                    }  else {
                        $actvTree[$act['parent_id']]['total'] += $act['total'];
                    }

                    if ( isset( $actvTree[ $actvTree[$act['parent_id']]['parent_id'] ]['total'] ) ) {
                        $actvTree[ $actvTree[$act['parent_id']]['parent_id'] ]['total'] += $act['total'];
                    } else {
                        $actvTree[ $actvTree[$act['parent_id']]['parent_id'] ]['total'] = $act['total'];
                    }
                }
            }
        }
        unset($actvTree['']);

        // get total
        $total = 0;
        foreach ($actvTree as $act) {
            if ( !isset($act['parent_id']) || empty($act['parent_id']) ) {
                $total += $act['total'];
            }
        }
        // other total
        $percent = ($realizations/$total)*100;
        $remain = $total - $realizations;

        // total of unmtachRealizations
        $listUnmatchRealizations = array();
        foreach ($T as $_kT => $_T) {
            if (!empty($_T) && is_array($_T)) {
                $listUnmatchRealizations[$_kT] = $_T;
                // iterate again to get the total
                foreach ($_T as $__T) {
                    $unmatchRealizations += $__T['total'];
                }
            }
        }
        $unmatch = false;
        if (!empty($listUnmatchRealizations)) {
            $unmatch = true;
        }

        // get list of activities
        $A = $this->Activity->find('list', array(
            'fields' => array('id', 'name')
        ));

        return array(
            'records' => $actvTree,
            'total' => $total,
            'total_realization' => $realizations,
            'total_percent' => $percent,
            'total_remain' => $remain,
            'unmatch' => $unmatch,
            'total_unmatch' => $unmatchRealizations,
            'list_unmatch' => $listUnmatchRealizations,
            'activities' => $A
        );
    }

    function __niceFundSourceName($f) {
        $ret = '';
        switch ($f) {
            case 'bind':
                $ret = 'Mengikat';
                break;
            case 'unbind':
                $ret = 'Tidak Mengikat';
                break;
            case 'pnbp':
                $ret = 'PNBP';
                break;
        }
        return $ret;
    }

    function __recPopTot(&$actvTree, $parent_id) {
        foreach ($actvTree as $actId => $act) {

            if ( isset($act['parent_id']) && $act['parent_id'] == $parent_id ) {

                if ( !isset($act['total']) ) {
                    // if we dont have total,
                    // we should check our child
                    // $this->__recPopTot(&$actvTree, $actId);
                } else {
                    // if we have total already
                    // sum it!
                    if ( !isset($actvTree[$parent_id]['total']) ) {

                        $actvTree[$parent_id]['total'] = $act['total'];
                    }  else {
                        $actvTree[$parent_id]['total'] += $act['total'];
                    }
                }


            }
        }
    }

    function getCompositionDetail($year = null, $activity_children = null) {
        if (is_null($year)) {
            $year = date('Y');
        }

        // attach containable
        $this->BudgetDetail->Behaviors->attach('Containable');
        $fields = array('id');
        $contain = array(
            'BudgetDetailDescription' => array(
                'fields' => array(
                    'unit_count', 'unit_amount'
                )
            ),
            'Budget' => array(
                'fields' => array('activity_id')
            ),
            'ActivityChild' => array(
                'fields' => array('code')
            )
        );

        $conditions = array(
            'Budget.budget_year' => $year
        );


        if ( is_array($activity_children) && !empty($activity_children) ) {
            $conditions['BudgetDetail.activity_child_id'] = $activity_children;
        }

        $records = $this->BudgetDetail->find('all', compact(
            'conditions', 'fields', 'order', 'limit',
            'page', 'recursive', 'group', 'contain'
            )
        );

        $total = array();
        foreach ( $records as $key => $record ) {
            foreach ( $record['BudgetDetailDescription'] as
                $__k => $budget_description ) {

                $__tot  = ($budget_description['unit_count']*$budget_description['unit_amount']);

                /*
                if ( !isset($total[ $record['ActivityChild']['code'] ]) ) {
                    $total[ $record['ActivityChild']['code'] ] = 0;
                }
                $total[ $record['ActivityChild']['code'] ] += $__tot;
                */
                if ( !isset($total[ $record['Budget']['activity_id'] ]
                    [ $record['ActivityChild']['code'] ]) ) {
                    $total[ $record['Budget']['activity_id'] ][ $record['ActivityChild']['code'] ] = 0;
                }
                $total[ $record['Budget']['activity_id'] ][ $record['ActivityChild']['code'] ] += $__tot;
            }
        }

        return $total;
    }

    function getComposition($year = null) {
        if (is_null($year)) {
            $year = date('Y');
        }

        $this->Behaviors->attach('Containable');
        $fields = array();
        $contain = array(
            'BudgetDetail' => array(
                'fields' => array(),
                'BudgetDetailDescription' => array(
                    'fields' => array(
                        'unit_count', 'unit_amount', 'fund_source'
                    )
                )
            )
        );
        $conditions = array(
            'Budget.budget_year' => $year
        );

        $records = $this->find('all', compact(
            'conditions', 'fields', 'order', 'limit',
            'page', 'recursive', 'group', 'contain'
            )
        );

        $total = array(
            'bind' => 0, 'unbind' => 0, 'pnbp' => 0
        );

        foreach ( $records as $key => $record ) {
            foreach ( $record['BudgetDetail'] as $_k => $budget_detail ) {
                foreach ( $budget_detail['BudgetDetailDescription'] as
                    $__k => $budget_description ) {

                    $__tot  = ($budget_description['unit_count']*$budget_description['unit_amount']);
                    $total[ $budget_description['fund_source'] ] += $__tot;
                }
            }
        }

        return $total;
    }

    function getTotalByMAK($mak) {
        $query  = 'SELECT SUM(bdd.unit_count*bdd.unit_amount) as total FROM ' . $this->useTable . ' b ';
        $query .= 'LEFT JOIN budget_details bd ON bd.budget_id = b.id ';
        $query .= 'LEFT JOIN budget_detail_descriptions bdd ON bdd.budget_detail_id = bd.id ';
        $query .= 'LEFT JOIN activity_children ac ON ac.id = bd.activity_child_id ';

        $where = 'WHERE';
        if ( is_array($mak) ) {
            $in = "";
            foreach ($mak as $v) {
                $in .= "'$v',";
            }
            // remove last comma
            $in = substr($in, 0, strlen($in) -1);
            $where .= ' ac.code IN(' . $in . ')';
        } else {
            $where .= " ac.code = '$mak'";
        }
        $query .= $where;
        $res = $this->query($query);

        $ret = 0;
        if (isset($res[0][0]['total'])) {
            $ret = $res[0][0]['total'];
        }

        return $ret;
    }

    function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) {
        $this->Behaviors->attach('Containable');
        $fields = array('id', 'activity_id', 'unit_code_id', 'budget_year', 'created');
        $contain = array(
            'User' => array(
                'fields' => array('name')
            ),
            'UnitCode' => array(
                'fields' => array('name')
            ),
            'Activity' => array(
                'fields' => array('name', 'code')
            ),
            'BudgetDetail' => array(
                'fields' => array(),
                'BudgetDetailDescription' => array(
                    'fields' => array('unit_count', 'unit_amount')
                )
            )
        );
        $recursive = 2;

        $records = $this->find('all', compact(
            'conditions', 'fields', 'order', 'limit',
            'page', 'recursive', 'group', 'contain'
            )
        );
        foreach ( $records as $key => $record ) {
            $total = 0;

            foreach ( $record['BudgetDetail'] as $budget_detail ) {
                foreach ( $budget_detail['BudgetDetailDescription'] as $budget_description ) {
                    $total += ($budget_description['unit_count']*$budget_description['unit_amount']);
                }
            }

            $records[$key][$this->name]['total'] = number_format($total, 2, '.', ',');
        }

        return $records;
    }

    function beforeValidate() {
        if (isset($this->data['Budget']['budget_year']['year']) &&
            is_array($this->data['Budget']['budget_year']) ) {
            $this->data['Budget']['budget_year'] = $this->data['Budget']['budget_year']['year']*1;
        }

        if (!isset($this->data['Budget']['budget_year']) ||
             empty($this->data['Budget']['budget_year']) ) {
                $this->data['Budget']['budget_year'] = date('Y');
        }
        $this->data['Budget']['budget_year'] = $this->data['Budget']['budget_year']*1;

        return true;
    }

    function vUniqueBudget($field) {
        $exists = $this->find('count', array(
            'conditions' => array(
                'Budget.budget_year' => $field['budget_year'],
                'Budget.activity_id' => $this->data['Budget']['activity_id'],
                'Budget.unit_code_id' => $this->data['Budget']['unit_code_id']
            )
        ));

        if ( $exists && !($this->id) ) {
            return false;
        }

        return true;
    }

    function vUnit($field) {
        return $this->UnitCode->find('count', array(
            'conditions' => array(
                'UnitCode.id' => $field["unit_code_id"]
            ),
            'recursive' => -1
        )) > 0;
    }

    function vActivity($field) {
        return $this->Activity->find('count', array(
            'conditions' => array(
                'Activity.id' => $field['activity_id']
            )
        )) > 0;
    }
}
?>